import asyncio
import json
import time

from datasets import load_dataset

from lagent.agents.stream import AsyncAgentForInternLM, AsyncMathCoder
from lagent.llms import INTERNLM2_META
from lagent.llms.vllm_wrapper import AsyncVllmModel
from lagent.prompts.parsers import ToolParser

# 设置异步事件循环
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

# 初始化 vLLM 模型
model = AsyncVllmModel(
    path='/root/autodl-tmp/models/internlm2_5-1_8b-chat',  # 使用通义千问2-7B指令模型
    meta_template=INTERNLM2_META,  # 使用 InternLM2 的元模板
    tp=1,  # 张量并行度
    top_k=1,  # 只保留概率最高的候选词
    temperature=1.0,  # 采样温度
    stop_words=['<|im_end|>', '\n```\n'],  # 停止词
    max_new_tokens=1024,  # 最大生成长度
)

# ----------------------- 测试数学解题功能 -----------------------
print('-' * 80, 'interpreter', '-' * 80)

# 加载数学问题数据集
ds = load_dataset('lighteval/MATH', split='test')
problems = [item['problem'] for item in ds.select(range(10))]  # 选取前10个问题

# 创建异步数学解题代理
coder = AsyncMathCoder(
    llm=model,
    interpreter=dict(
        type='lagent.actions.AsyncIPythonInterpreter',  # 使用异步 Python 解释器
        max_kernels=200  # 最大并发内核数
    ),
    output_format=ToolParser(
        'interpreter',  # 工具类型
        template=(  # 提示模板
            'Integrate step-by-step reasoning and Python code to solve math problems '
            'using the following guidelines:\n'
            '- Analyze the question and write jupyter code to solve the problem;\n'
            r"- Present the final result in LaTeX using a '\boxed{{}}' without any "
            'units. \n'
        ),
        begin='\n```python\n',  # Python代码块开始标记
        end='\n```\n'  # Python代码块结束标记
    ))

# 开始批量解题
tic = time.time()  # 记录开始时间
# 为每个问题创建一个异步任务
coros = [coder(query, session_id=i) for i, query in enumerate(problems)]
# 并发执行所有任务
res = loop.run_until_complete(asyncio.gather(*coros))
print('-' * 120)
print(f'time elapsed: {time.time() - tic}')  # 打印总耗时

# 保存解题步骤到文件
with open('./tmp_3.json', 'w') as f:
    json.dump([coder.get_steps(i) for i in range(len(res))],
              f,
              ensure_ascii=False,
              indent=4)
